/*!
	@author Angéline Guignard & Adrien Megueddem
	@copyright Imagimp
	@language C
	@header Header de Gestion de calques
		La gestion de tous ce qui concerne les calques comme l'ajout
		de calque, la suppression de calque, l'opacité de calque etc...
	@updated 2012-12-08
 */

/*!
	@class Calques
	@discussion Cette classe calques permet de faire
	la gestion de tous ce qui concerne les calques comme l'ajout
	de calque, la suppression de calque, l'opacité de calque etc...
*/

#ifndef _GLIMAGIMP__CALQUES_H___
#define _GLIMAGIMP__CALQUES_H___

#include "image.h"
#include "lut.h"

/***************
** Structures **
***************/

/*!
    @typedef Structure d'un calque
    @abstract Structure qui définit ce qu'est un calque
    @field nextCalque Description du premier champs
    @field prevCalque Description du troisième champ
    @field opacity paramètre d'opacité du calque
    @discussion Ici tu racontes ta vie ou celle de la fonction
 */
typedef struct calque{
	Image* image;
	int source;
	int key;
	int w;
	int h;
 	struct Calque* nextCalque;
 	struct Calque* prevCalque;
	float opacity; // 1 =  opacité totale 0 = transparence totale
	unsigned int mix;
	ListeLut llut;
}Calque;

typedef Calque* ListeCalques;

/////////////////
// Définitions //
/////////////////

/*!
	changeOpacity() permet de changer le coefficient d'opacité du calque.
	@param c
        	Calque* c on prend en paramètre le calque concerné.
	@param o
		float o coefficient d'opacité.	
	@result
		change le coefficient d'opacité.
 */
int changeOpacity(Calque* c, float o);

/*!
	newCalque() permet de creer un calque suivant.
	@result
		crée une nouelle liste de calque et un nouveau calque.
 */
ListeCalques newCalque();

/*!
	createCalque() permet de creer un calque suivant.
    @param image
    	Image* image on prend en paramètre l'image chargée.
    @param c
        ListeCalques c on prend en paramètre le calque précédent.
	@result
		crée un calque pour une image donné et l'ajoute à la liste.
 */
ListeCalques createCalque(Storage* storage, ListeCalques c);

/*!
	addCalque() permet de creer un calque suivant.
    @param image
    	Image* image on prend en paramètre l'image chargée.
    @param c
        ListeCalques c on prend en paramètre le calque précédent.
	@result
		ajoute un nouveau calque à la liste des calques.
 */
ListeCalques addCalque(Storage* storage, ListeCalques c);

/*!
	changeView() permet de changer l'image courante que l'utilisateur voit soit image source soit image finale du calque.
    @param l
    	ListeCalques l on prend en paramètre la liste de calque.
	@param storage
    	Storage* storage on prend en paramètre le storage.
	@result
		retourne un tableau de pixel.
*/
unsigned char* changeView(ListeCalques l, Storage* storage);

/*!
	afficherCalques() permet d'afficher toute la liste des calques.
    @param l
    	ListeCalques l on prend en paramètre la liste de calque.
    @param storage
    	Storage* storage on prend en paramètre le storage.
	@result
		affiche la liste des calques.
*/
void afficherCalques(ListeCalques l, Storage* storage);

/*!
	nextCalque() permet de se déplacer d'un calque suivant.
    @param l
    	ListeCalques l on prend en paramètre la liste de calque.
	@result
		Place le pointer de la liste des calques sur le calque suivant.
		Ne change pas le pointer si il n'y a pas de calque suivant.
*/
ListeCalques nextCalque(ListeCalques l);

/*!
	prevCalque() permet de se déplacer d'un calque précédent.
    @param l
    	ListeCalques l on prend en paramètre la liste de calque.
	@result
		Place le pointer de la liste des calques sur le calque précédent.
		Ne change pas le pointer si il n'y a pas de calque suivant.
*/
ListeCalques prevCalque(ListeCalques l);

/*!
	lastCalque() permet de se placer sur le dernier calque de la liste.
    @param l
    	ListeCalques l on prend en paramètre la liste de calque.
	@result
		Place le pointer de la liste des calques sur le dernier calque de la liste.
*/
ListeCalques lastCalque(ListeCalques l);

/*!
	firstCalque() permet de se placer sur le premier calque de la liste.
    @param l
    	ListeCalques l on prend en paramètre la liste de calque.
	@result
		Place le pointer de la liste des calques sur le premier calque de la liste.
*/
ListeCalques firstCalque(ListeCalques l);

/*!
	getKey() permet de récupérer la clé du calque pour retrouver l'image source dans le storage.
	@param l
        ListeCalques l on  prend en paramètre la liste de calque.
	@result
		on retourne la clé du calque courant.
*/
int getKey(ListeCalques l);

/*!
	switchCalque() permet de changer de calque.
	@param c
        	Calque* c on prend en paramètre le calque précédent.
	@result
		change le poiteur (de la liste) de calque.
*/
unsigned char* switchCalque(ListeCalques* l, Storage* storage);

/*!
	delCalque() permet de supprimer un calque.
	@param c
        	Calque* c on prend en paramètre le calque précédent.
	@result
		supprime calque.
*/
ListeCalques delCalque(ListeCalques l);

/*!
	switchMix() permet de changer le type de fusion du calque.
	@param c
        	Calque* c on prend en paramètre le calque courant.
	@result
		renvoit 0 ou 1 en fonction du type choisit.
*/
void switchMix(Calque* c);

/*!
	increaseOpacity() permet d'augmenter l'opacité du calque.
	@param c
        	Calque* c on prend en paramètre le calque courant.
	@result
		change l'opacité.
*/
unsigned char* increaseOpacity(Calque* c, Storage* storage);

/*!
	decreaseOpacity() permet de diminuer l'opacité du calque.
	@param c
        	Calque* c on prend en paramètre le calque courant.
	@result
		change l'opacité.
*/
unsigned char* decreaseOpacity(Calque* c, Storage* storage);

// Image* sumCalque(Calque* c, Storage* storage);

// Image* productCalque(Calque* c, Storage* storage);

void updateCalque(Calque* c, Storage* storage);

extern void refreshLut(ListeLut l, Calque* c);

extern void setLut(ListeLut l, Calque* c);

extern ListeLut delLut(ListeLut l);

/*! greyScale() on modifie l'image pour la mettre en niveau de gris
	@result
		on renvoit le lut crée
 */
extern void greyScale(Calque* c);

#endif